package com.pactera.asmp.server.service;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.time.LocalDateTime;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.pactera.asmp.server.common.bug.IBugHandler;
import com.pactera.asmp.server.common.bug.impl.AbstractBugHandler;
import com.pactera.asmp.server.common.constants.ResultCode;
import com.pactera.asmp.server.common.exception.CustomException;
import com.pactera.asmp.server.common.logprint.utils.CollectionUtils;
import com.pactera.asmp.server.dao.DeviceInfoMapper;
import com.pactera.asmp.server.dao.MasterComputerMapper;
import com.pactera.asmp.server.dao.ProductionLineHistoryMapper;
import com.pactera.asmp.server.dao.ProductionLineMapper;
import com.pactera.asmp.server.dao.ProjectMapper;
import com.pactera.asmp.server.dao.ProjectModuleMapper;
import com.pactera.asmp.server.dao.ProjectProductionConfigMapper;
import com.pactera.asmp.server.entity.ProductionLine;
import com.pactera.asmp.server.entity.ProductionLineExample;
import com.pactera.asmp.server.entity.ProductionLineHistory;
import com.pactera.asmp.server.entity.ProductionLineSearchDTO;
import com.pactera.asmp.server.entity.ProjectModuleDTO;
import com.pactera.asmp.server.entity.ProjectProductionConfig;
import com.pactera.asmp.server.entity.ProjectProductionConfigExample;
import com.pactera.asmp.server.entity.ResponseResult;
import com.pactera.asmp.server.pojo.DeviceInfo;
import com.pactera.asmp.server.pojo.MasterComputer;
import com.pactera.asmp.server.pojo.ProductionLineBuildNoticeInfo;
import com.pactera.asmp.server.pojo.ProductionLineHistoryInfo;
import com.pactera.asmp.server.pojo.ProductionLineInfo;
import com.pactera.asmp.server.pojo.ProjectInfo;
import com.pactera.asmp.server.pojo.User;
import com.pactera.asmp.server.pojo.WSMessage;

@Service
public class ProductionLineServiceImpl implements IProductionLineService {

    private Logger log = LoggerFactory.getLogger(ProductionLineServiceImpl.class);

    @Autowired
    private ProjectMapper projectMapper;

    @Autowired
    private ProjectModuleMapper projectModuleMapper;

    @Autowired
    private ProjectProductionConfigMapper projectProductionConfigMapper;

    @Autowired
    private ProductionLineMapper productionLineMapper;

    @Autowired
    private ProductionLineHistoryMapper productionLineHistoryMapper;

    @Autowired
    private MasterComputerMapper masterComputerMapper;

    @Autowired
    private IDeviceServcie deviceServcie;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DeviceInfoMapper mDeviceInfoMapper;

    @Value("${asmp.mastercomputer.osname}")
    private String osName = "OS";

    @Override
    public List<ProductionLine> getProductionLineListByProjectId(Integer projectId) {
        if (null == projectId || 0 == projectId) {
            throw new CustomException(ResultCode.PARAM_IS_BLANK);
        }

        ProjectProductionConfigExample example = new ProjectProductionConfigExample();
        example.createCriteria().andProjectIdEqualTo(projectId);
        List<ProjectProductionConfig> projectProductionConfigs = projectProductionConfigMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(projectProductionConfigs)) {
            return null;
        }
        ProjectProductionConfig projectProductionConfig = projectProductionConfigs.get(0);
        // 校验输入的流水线信息
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setBasicAuth(projectProductionConfig.getProductionUsername(), projectProductionConfig.getProductionPassword());
        HttpEntity<String> httpEntity = new HttpEntity<>(httpHeaders);
        ResponseEntity<String> response = restTemplate.exchange(projectProductionConfig.getProductionUrl(), HttpMethod.GET, httpEntity, String.class);
        if(HttpStatus.SC_OK != response.getStatusCodeValue()) {
            throw new CustomException(ResultCode.BUSINESS_PROJECT_PRODUCTION_LINE_ERROR);
        }
        String msg = response.getBody();
        try {
            JSONObject jsonObject = JSONObject.parseObject(msg);
            List<Map<String, Object>> jobs = (List<Map<String, Object>>)jsonObject.get("jobs");
            if(CollectionUtils.isEmpty(jobs)) {
                throw new CustomException(ResultCode.BUSINESS_PROJECT_PRODUCTION_LINE_ERROR);
            }
            ProductionLineExample productionLineExample = new ProductionLineExample();
            for(Map<String, Object> map : jobs) {
                productionLineExample.or().andProjectIdEqualTo(projectId).andJobNameEqualTo(map.get("name").toString()).andJobUrlEqualTo(map.get("url").toString());
            }
            List<ProductionLine> productionLines = productionLineMapper.selectByExample(productionLineExample);
            return jobs.stream().map(job -> {
                if(CollectionUtils.isNotEmpty(productionLines)) {
                    Optional<ProductionLine> optional = productionLines.stream()
                            .filter(x -> StringUtils.equals(x.getJobName(), job.get("name").toString()) && StringUtils.equals(x.getJobUrl(), job.get("url").toString())).findFirst();
                    if(optional.isPresent()) {
                        return optional.get();
                    }
                }
                ProductionLine productionLine = new ProductionLine();
                productionLine.setJobName(job.get("name").toString());
                productionLine.setJobUrl(job.get("url").toString());
                return productionLine;
            }).collect(Collectors.toList());
        }catch (Exception ex) {
            log.error("production error. {}, {}", msg, ex.getMessage());
            throw new CustomException(ResultCode.BUSINESS_PROJECT_PRODUCTION_LINE_ERROR);
        }
    }

    @Override
    public List<ProductionLineInfo> getProductionLineList(ProductionLineSearchDTO productionLineSearchDTO) {
        ProductionLineExample productionLineExample = new ProductionLineExample();
        ProductionLineExample.Criteria criteria = productionLineExample.createCriteria();
        if(null != productionLineSearchDTO.getProjectId()) {
            criteria.andProjectIdEqualTo(productionLineSearchDTO.getProjectId());
        }
        if(StringUtils.isNotEmpty(productionLineSearchDTO.getJobName())) {
            criteria.andJobNameLike("%" + productionLineSearchDTO.getJobName() + "%");
        }
        List<ProductionLine> productionLines = productionLineMapper.selectByExample(productionLineExample);
        if(CollectionUtils.isEmpty(productionLines)) {
            return Lists.newArrayList();
        }
        Map<Integer, List<ProductionLine>> productionLineMap = productionLines.stream().collect(Collectors.groupingBy(ProductionLine::getProjectId));
        List<Integer> projectIds = productionLines.stream().map(ProductionLine::getProjectId).distinct().collect(Collectors.toList());
        Map<Integer, ProjectInfo> projectInfoMap = Maps.newHashMap();
        Map<Integer, ProjectProductionConfig> projectProductionConfigMap = Maps.newHashMap();
        if(CollectionUtils.isNotEmpty(projectIds)) {
            List<ProjectInfo> projectInfos = projectMapper.queryByPrimaryKeys(projectIds);
            if(CollectionUtils.isNotEmpty(projectInfos)) {
                projectInfoMap.putAll(projectInfos.stream().collect(Collectors.toMap(ProjectInfo::getId, x -> x, (v1, v2) -> v1)));
            }

            ProjectProductionConfigExample example = new ProjectProductionConfigExample();
            example.createCriteria().andProjectIdIn(projectIds);
            List<ProjectProductionConfig> projectProductionConfigs = projectProductionConfigMapper.selectByExample(example);
            if(CollectionUtils.isNotEmpty(projectProductionConfigs)) {
                projectProductionConfigMap.putAll(projectProductionConfigs.stream().collect(Collectors.toMap(ProjectProductionConfig::getProjectId, x -> x, (v1, v2) -> v1)));
            }
        }

        List<Integer> projectModuleIds = productionLines.stream().map(ProductionLine::getProjectModuleId).distinct().collect(Collectors.toList());
        Map<Integer, String> projectModuleNameMap = Maps.newHashMap();
        if(CollectionUtils.isNotEmpty(projectModuleIds)) {
            List<ProjectModuleDTO> projectModuleDTOs = projectModuleMapper.selectByIds(projectModuleIds);
            if(CollectionUtils.isNotEmpty(projectModuleDTOs)) {
                projectModuleNameMap.putAll(projectModuleDTOs.stream().collect(Collectors.toMap(ProjectModuleDTO::getId, ProjectModuleDTO::getName)));
            }
        }

        List<ProductionLineInfo> resultInfos = Lists.newArrayList();
        for(Integer key :productionLineMap.keySet()) {
            ProductionLineInfo productionLineInfo = new ProductionLineInfo();
            productionLineInfo.setProjectId(key);
            productionLineInfo.setProjectName(projectInfoMap.getOrDefault(key, new ProjectInfo()).getProjectName());
            ProjectProductionConfig projectProductionConfig = projectProductionConfigMap.getOrDefault(key, new ProjectProductionConfig());
            productionLineInfo.setProductionTool(projectProductionConfig.getProductionTool());
            productionLineInfo.setProductionUrl(projectProductionConfig.getProductionUrl());
            productionLineInfo.setProductionLineVos(productionLineMap.get(key).stream().map(productionLine -> {
                ProductionLineInfo.ProductionLineVo productionLineVo = new ProductionLineInfo.ProductionLineVo();
                BeanUtils.copyProperties(productionLine, productionLineVo);
                productionLineVo.setProjectModuleName(projectModuleNameMap.get(productionLine.getProjectModuleId()));
                return productionLineVo;
            }).collect(Collectors.toList()));
            resultInfos.add(productionLineInfo);
        }
        return resultInfos;
    }

    @Override
    public ResponseResult batchProductionLine(ProductionLineInfo productionLineInfo) {
        ProductionLineExample productionLineExample = new ProductionLineExample();
        productionLineExample.createCriteria().andProjectIdEqualTo(productionLineInfo.getProjectId());
        List<ProductionLine> productionLines = productionLineMapper.selectByExample(productionLineExample);

        User currUser = (User) SecurityUtils.getSubject().getPrincipal();
        if (currUser == null) throw new CustomException(ResultCode.PERMISSION_EXPIRE);

        LocalDateTime localDateTime = LocalDateTime.now();
        if(CollectionUtils.isEmpty(productionLines)) {
            for(ProductionLineInfo.ProductionLineVo productionLineVo : productionLineInfo.getProductionLineVos()) {
                ProductionLine productionLine = new ProductionLine();
                productionLine.setJobName(productionLineVo.getJobName());
                productionLine.setJobUrl(productionLineVo.getJobUrl());
                productionLine.setProjectId(productionLineInfo.getProjectId());
                productionLine.setProjectModuleId(productionLineVo.getProjectModuleId());
                productionLine.setCreateTime(localDateTime);
                productionLine.setCreateUid(currUser.getId());
                productionLineMapper.insertSelective(productionLine);
            }
        }else {
            for(ProductionLineInfo.ProductionLineVo productionLineVo : productionLineInfo.getProductionLineVos()) {
                Optional<ProductionLine> optional = productionLines.stream()
                        .filter(x -> StringUtils.equals(x.getJobName(), productionLineVo.getJobName())
                                && StringUtils.equals(x.getJobUrl(), productionLineVo.getJobUrl())).findFirst();
                if(optional.isPresent()) {
                    ProductionLine productionLine = optional.get();
                    productionLine.setProjectId(productionLineInfo.getProjectId());
                    productionLine.setProjectModuleId(productionLineVo.getProjectModuleId());
                    productionLine.setUpdateTime(localDateTime);
                    productionLine.setUpdateUid(currUser.getId());
                    productionLineMapper.updateByPrimaryKeySelective(productionLine);
                }else {
                    ProductionLine productionLine = new ProductionLine();
                    productionLine.setJobName(productionLineVo.getJobName());
                    productionLine.setJobUrl(productionLineVo.getJobUrl());
                    productionLine.setProjectId(productionLineInfo.getProjectId());
                    productionLine.setProjectModuleId(productionLineVo.getProjectModuleId());
                    productionLine.setCreateTime(localDateTime);
                    productionLine.setCreateUid(currUser.getId());
                    productionLineMapper.insertSelective(productionLine);
                }
            }
            List<ProductionLine> delProductionLines = productionLines.stream().filter(x -> {
                return productionLineInfo.getProductionLineVos().stream().noneMatch(vo -> StringUtils.equals(x.getJobName(), vo.getJobName())
                                && StringUtils.equals(x.getJobUrl(), vo.getJobUrl()));
            }).collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(delProductionLines)) {
                for(ProductionLine productionLine : delProductionLines) {
                    ProductionLineHistory productionLineHistory =new ProductionLineHistory();
                    BeanUtils.copyProperties(productionLine, productionLineHistory);
                    productionLineHistory.setId(null);
                    productionLineHistory.setProductionLineId(productionLine.getId());
                    productionLineHistoryMapper.insertSelective(productionLineHistory);
                }
                productionLineExample = new ProductionLineExample();
                productionLineExample.createCriteria().andIdIn(delProductionLines.stream().map(x -> x.getId()).distinct().collect(Collectors.toList()));
                productionLineMapper.deleteByExample(productionLineExample);
            }
        }
        return ResponseResult.defaultSuccess(null);
    }

    @Override
    public ResponseResult updateProductionLine(ProductionLine productionLine) {
        ProductionLine oldProductionLine = productionLineMapper.selectByPrimaryKey(productionLine.getId());
        if(null == oldProductionLine || null == oldProductionLine.getId()) {
            throw new CustomException(ResultCode.BUSINESS_PROJECT_PRODUCTION_LINE_NOT_EXISTED);
        }
        User currUser = (User) SecurityUtils.getSubject().getPrincipal();
        if (currUser == null) throw new CustomException(ResultCode.PERMISSION_EXPIRE);

        productionLine.setUpdateTime(LocalDateTime.now());
        productionLine.setUpdateUid(currUser.getId());
        productionLineMapper.updateByPrimaryKeySelective(productionLine);
        return ResponseResult.defaultSuccess(null);
    }

    @Override
    public ResponseResult updateProductionLineConfig(ProjectProductionConfig projectProductionConfig) {
        ProjectProductionConfig oldProjectProductionConfig = projectProductionConfigMapper.selectByPrimaryKey(projectProductionConfig.getId());
        if(null == oldProjectProductionConfig || null == oldProjectProductionConfig.getId()) {
            throw new CustomException(ResultCode.BUSINESS_PROJECT_PRODUCTION_LINE_CONFIG_NOT_EXISTED);
        }
        User currUser = (User) SecurityUtils.getSubject().getPrincipal();
        if (currUser == null) throw new CustomException(ResultCode.PERMISSION_EXPIRE);

        projectProductionConfig.setUpdateTime(LocalDateTime.now());
        projectProductionConfig.setUpdateUid(currUser.getId());
        projectProductionConfigMapper.updateByPrimaryKeySelective(projectProductionConfig);
        return ResponseResult.defaultSuccess(null);
    }

    @Override
    public ResponseResult<Boolean> validateProductionLineConfig(ProjectProductionConfig projectProductionConfig) {
        // 校验输入的流水线信息
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.setBasicAuth(projectProductionConfig.getProductionUsername(), projectProductionConfig.getProductionPassword());
            HttpEntity<String> httpEntity = new HttpEntity<>(httpHeaders);
            ResponseEntity<String> response = restTemplate.exchange(projectProductionConfig.getProductionUrl(), HttpMethod.GET, httpEntity, String.class);
            if(HttpStatus.SC_OK != response.getStatusCodeValue()) {
                log.error("production error. {}, {}", response.getStatusCodeValue(), response.getBody());
                return ResponseResult.defaultSuccess(Boolean.FALSE);
            }
            String msg = response.getBody();
            JSONObject jsonObject = JSONObject.parseObject(msg);
            List<Map<String, Object>> jobs = (List<Map<String, Object>>)jsonObject.get("jobs");
            if(CollectionUtils.isEmpty(jobs)) {
                return ResponseResult.defaultSuccess(Boolean.FALSE);
            }
            return ResponseResult.defaultSuccess(Boolean.TRUE);
        }catch (Exception ex) {
            log.error("production error. {}", ex.getMessage());
            return ResponseResult.defaultSuccess(Boolean.FALSE);
        }
    }

    @Override
    public ResponseResult noticeBuildSuccess(HttpServletRequest request,
            @Valid ProductionLineBuildNoticeInfo productionLineBuildNoticeInfo) {
        String token = request.getHeader("Authorization");
        String regex = "^Basic\\s.+$";

        if (StringUtils.isEmpty(token) || !token.matches(regex)) {
            return new ResponseResult(ResultCode.USER_LOGIN_ERROR);
        }
        // 获取 basic token
        log.info("token:{}", token);
        try {
            token = new String(Base64.getDecoder().decode(token.substring(6)), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error("{}", e.getMessage());
            return new ResponseResult(ResultCode.USER_LOGIN_ERROR);
        }
        log.info("获取的 Authorization token: {}", token);
        // basic token 格式为 username:password
        String[] res = token.split(":");
        // 判断是否已配置过流水线配置
        ProjectProductionConfigExample projectProductionConfigExample = new ProjectProductionConfigExample();
        projectProductionConfigExample.createCriteria().andProductionUrlEqualTo(productionLineBuildNoticeInfo.getProductionUrl())
                .andProductionUsernameEqualTo(res[0]).andProductionPasswordEqualTo(res[1]);
        List<ProjectProductionConfig> projectProductionConfigs = projectProductionConfigMapper.selectByExample(projectProductionConfigExample);
        if(CollectionUtils.isEmpty(projectProductionConfigs)) {
            return new ResponseResult(ResultCode.BUSINESS_PROJECT_PRODUCTION_LINE_CONFIG_NOT_EXISTED);
        }
        Map<Integer, ProjectProductionConfig> configMap= projectProductionConfigs.stream().collect(Collectors.toMap(ProjectProductionConfig::getProjectId, x -> x, (v1, v2) -> v1));
        // 更新流水线信息
        ProductionLineExample productionLineExample = new ProductionLineExample();
        productionLineExample.createCriteria().andJobNameEqualTo(productionLineBuildNoticeInfo.getJobName()).andJobUrlEqualTo(productionLineBuildNoticeInfo.getJobUrl());
        List<ProductionLine> productionLines = productionLineMapper.selectByExample(productionLineExample);
        if(CollectionUtils.isEmpty(productionLines)) {
            return new ResponseResult(ResultCode.BUSINESS_PROJECT_PRODUCTION_LINE_NOT_EXISTED);
        }
        List<ProductionLineHistory> productionLineHistorys = Lists.newArrayList();
        for(ProductionLine productionLine: productionLines) {
            productionLine.setDownloadUrl(productionLineBuildNoticeInfo.getDownloadUrl());
            productionLine.setJobVersion(productionLineBuildNoticeInfo.getJobVersion());
            productionLine.setUpdateContent(productionLineBuildNoticeInfo.getUpdateContent());
            productionLine.setUpdateTime(LocalDateTime.now());
            productionLine.setUpdateUid(0); // 上报数据更新
            productionLineMapper.updateByPrimaryKeySelective(productionLine);
            this.insertHistory(productionLine, productionLineHistorys);
        }
        List<Integer> projectModuleIds = productionLines.stream().map(ProductionLine::getProjectModuleId).distinct().collect(Collectors.toList());
        Map<Integer, String> projectModuleNameMap = Maps.newHashMap();
        if(CollectionUtils.isNotEmpty(projectModuleIds)) {
            List<ProjectModuleDTO> projectModuleDTOs = projectModuleMapper.selectByIds(projectModuleIds);
            if(CollectionUtils.isNotEmpty(projectModuleDTOs)) {
                projectModuleNameMap.putAll(projectModuleDTOs.stream().collect(Collectors.toMap(ProjectModuleDTO::getId, ProjectModuleDTO::getName)));
            }
        }
        for(ProductionLineHistory productionLineHistory: productionLineHistorys) {
            // 下发通知给上位机
            String moduleName = projectModuleNameMap.get(productionLineHistory.getProjectModuleId());
            if(StringUtils.isEmpty(moduleName)) {
                log.warn("moduleName not exist. {}", JSONObject.toJSONString(productionLineHistory));
                continue;
            }
            // 判断是os还是其他模块
            if(StringUtils.equals(osName, moduleName)) {
                ProjectProductionConfig projectProductionConfig = configMap.get(productionLineHistory.getProjectId());
                if(null == projectProductionConfig || null == projectProductionConfig.getOsMcId()) {
                    log.warn("OsMcId not exist. {}", JSONObject.toJSONString(productionLineHistory));
                    continue;
                }
                this.sendSuccessMessage("990", productionLineHistory, projectProductionConfig.getOsMcId());
            }else {
                ProjectProductionConfig projectProductionConfig = configMap.get(productionLineHistory.getProjectId());
                if(null == projectProductionConfig || null == projectProductionConfig.getHmiMcId()) {
                    log.warn("HmiMcId not exist. {}", JSONObject.toJSONString(productionLineHistory));
                    continue;
                }
                this.sendSuccessMessage("991", productionLineHistory, projectProductionConfig.getHmiMcId());
            }
        }

        return ResponseResult.defaultSuccess(null);
    }

    private void sendSuccessMessage(String msgCode, ProductionLineHistory productionLineHistory, Integer masterComputerId) {
        MasterComputer masterComputer = masterComputerMapper.selectByPrimaryKey(masterComputerId);
        List<DeviceInfo> deviceInfos = mDeviceInfoMapper.selectByMasterComputerIds(Lists.newArrayList(masterComputer.getId()), null);
        // 筛选在线设备
        deviceInfos = deviceInfos.stream().filter(x -> x.getStatus() == 0).collect(Collectors.toList());
        try {
            WSMessage message = new WSMessage();
            message.setMsgcode(msgCode);
            message.setDescribe("流水线任务");
            ProductionLineHistoryInfo productionLineHistoryInfo = new ProductionLineHistoryInfo();
            BeanUtils.copyProperties(productionLineHistory, productionLineHistoryInfo);
            productionLineHistoryInfo.setMasterComputerId(masterComputer.getId());
            message.setList(Lists.newArrayList(JSONObject.toJSONString(productionLineHistoryInfo)));
            // 存在车机设备就发到车机设备，否则推送到辅助设备
            Optional<DeviceInfo> vehicle = deviceInfos.stream().filter(x -> x.getType() == null && !x.getAuxiliary() && StringUtils.isNotEmpty(x.getDisplayIdsStr())).findFirst();
            if(vehicle.isPresent()) {
                deviceServcie.sendToDeviceMessage(vehicle.get().getDuid(), JSONObject.toJSONString(message));
            }else {
                List<DeviceInfo> auxiliarys = deviceInfos.stream().filter(x -> x.getAuxiliary()).collect(Collectors.toList());
                for(DeviceInfo deviceInfo : auxiliarys) {
                    deviceServcie.sendToDeviceMessage(deviceInfo.getDuid(), JSONObject.toJSONString(message));
                }
            }
            
        } catch (IOException e) {
            log.error("send masterComputer msg error. {}", e.getMessage());
        }
    }

    private void insertHistory(ProductionLine productionLine, List<ProductionLineHistory> productionLineHistorys) {
        ProductionLineHistory productionLineHistory =new ProductionLineHistory();
        BeanUtils.copyProperties(productionLine, productionLineHistory);
        productionLineHistory.setId(null);
        productionLineHistory.setProductionLineId(productionLine.getId());
        productionLineHistoryMapper.insertSelective(productionLineHistory);
        productionLineHistorys.add(productionLineHistory);
    }

    @Override
    public ResponseResult deleteProductionLine(Integer id) {
        ProductionLine productionLine = productionLineMapper.selectByPrimaryKey(id);
        if(null == productionLine) {
            throw new CustomException(ResultCode.BUSINESS_PROJECT_PRODUCTION_LINE_NOT_EXISTED);
        }
        ProductionLineHistory productionLineHistory =new ProductionLineHistory();
        BeanUtils.copyProperties(productionLine, productionLineHistory);
        productionLineHistory.setId(null);
        productionLineHistory.setProductionLineId(productionLine.getId());

        User currUser = (User) SecurityUtils.getSubject().getPrincipal();
        if (currUser == null) throw new CustomException(ResultCode.PERMISSION_EXPIRE);
        productionLineHistory.setUpdateUid(currUser.getId());
        productionLineHistory.setUpdateTime(LocalDateTime.now());

        productionLineMapper.deleteByPrimaryKey(id);
        productionLineHistoryMapper.insertSelective(productionLineHistory);
        return ResponseResult.defaultSuccess(null);
    }

    @Override
    @Transactional
    public void deleteProductionLineByProjectIds(List<Integer> projectIds) {
        ProductionLineExample productionLineExample = new ProductionLineExample();
        productionLineExample.createCriteria().andProjectIdIn(projectIds);
        List<ProductionLine> productionLines = productionLineMapper.selectByExample(productionLineExample);
        if(CollectionUtils.isNotEmpty(productionLines)) {
            for(ProductionLine productionLine : productionLines) {
                ProductionLineHistory productionLineHistory =new ProductionLineHistory();
                BeanUtils.copyProperties(productionLine, productionLineHistory);
                productionLineHistory.setId(null);
                productionLineHistory.setProductionLineId(productionLine.getId());
                productionLineHistoryMapper.insertSelective(productionLineHistory);
            }
            productionLineMapper.deleteByExample(productionLineExample);
        }
    }

    @Override
    public ResponseResult<Map<String, Map<String, String>>> getProductAndProject(ProjectProductionConfig projectProductionConfig) {
        Map<String, Map<String, String>> resultMap = Maps.newHashMap();
        IBugHandler handler = AbstractBugHandler.getBugHandler(projectProductionConfig.getBugSubmitTo());
        if(null != handler) {
            Map<String, String> productionMap = handler.getProductionList(projectProductionConfig);
            Map<String, String> projectMap = handler.getProjectList(projectProductionConfig);
            Map<String, String> priorityMap = handler.getPriorityList(projectProductionConfig);
            if(MapUtils.isEmpty(projectMap)
                    || (MapUtils.isEmpty(productionMap) && StringUtils.equals("ZENTAO", projectProductionConfig.getBugSubmitTo()))
                    || (MapUtils.isEmpty(priorityMap) && StringUtils.equals("JIRA", projectProductionConfig.getBugSubmitTo()))) {
                throw new CustomException(ResultCode.BUSINESS_PROJECT_PRODUCTION_CONFIG_ERROR);
            }
            resultMap.put("product", productionMap);
            resultMap.put("project", projectMap);
            resultMap.put("priority", priorityMap);
        }
        return ResponseResult.defaultSuccess(resultMap);
    }

}
